// 接口可以被继承，type虽然也可以进行数据类型的约束，type却无法被继承
interface Pet { name: string; health: string; toHealth(): void }
// 接口的继承
interface Dog extends Pet { hobby: string; toPlay(): void }

// 接口对方法的参数进行，数据类型约束
let dog:Dog = { name: '修狗', health: '健康', toHealth() {}, hobby: '吃饭', toPlay() {} }
function getHobby(pet: Dog) {
  console.log(pet.hobby)
}
getHobby(dog)

// 对不同的类，提供统一的属性与方法名
interface List {
  add(): void
  remove(): void
}
class SetList implements List {
  add(): void {}
  remove(): void {}
}
class MapList implements List {
  add(): void {}
  remove(): void {}
}

// 可索引签名
interface Human {
  name: string,
  age: number
  [x: string]: any
}
let obj:Human = {
  name: '张三',
  age: 18,
  [Symbol('job')]: '医生',
  100: 120
}

// 索引访问类型
const carId = Symbol('price')
interface Car {
  name: string
  price: number,
  [carId]: number
}
type A = Car['name']
type B = Car[typeof carId]
type C = Car['name' | 'price']

type CarKeys = keyof Car
let cKeys:CarKeys = "name"
let bKeys: 'name' | 'price' | typeof carId = 'name'  // 或者，carId

// 接口合并
interface Obj1 { name: string }
interface Obj1 { age: number }
let obj2: Obj1 = { name: "张三", age: 18 }

// 继承多个接口
interface DaGongRen extends Human,Car {}
let xiaoming: DaGongRen = { name: '小明', age: 18, price: 100, [carId]: 101 }

// type的交叉类型，而接口没有交叉类型
type Obj2 = { name: string }
type Obj3 = { age: number }
let obj3: Obj2 & Obj3 = { name: '张三', age: 5 }

// 加上这一句，就不会触发全局变量名检查。全局变量名检查，就是所有ts文件里的变量都不能重名
export {}